package juego;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.swing.JOptionPane;

import exceptions.DestinoException;
import exceptions.EspejoException;
import exceptions.OrigenException;
import exceptions.ParedException;
import exceptions.TableroException;
import exceptions.TrampaException;

public class Parser{
	public static final int FILA=0;
	public static final int COL=1;
	public static final int TIPO=2;
	public static final int ROT=3;
	public static final int ROJO=4;
	public static final int VERDE=5;
	public static final int AZUL=6;
	
	public static final int ORIG=1;
	public static final int DEST=2;
	public static final int SIMPLE=3;
	public static final int DOBLE=4;
	public static final int SEMI=5;
	public static final int PARED=6;
	public static final int TRAMPA=7;
	
	public Tablero parser(File arch, boolean guardado) throws IOException, NumberFormatException {
		BufferedReader inputString;
		inputString = new BufferedReader(new FileReader(arch));
		
		String s, nivel, cant, user=null;
		int fil,col;
		
		try{
			if(guardado)
				user=inputString.readLine();
			
			if((s=inputString.readLine())==null)
				throw new IOException("Error en el archivo " + arch.getName() + ", se encuentra vacio");
				
			//pasa comentarios y lineas vacias de largo
			while(isVoid(s)){
				s=inputString.readLine();
			}
		    
			//nivel
			StringTokenizer st = new StringTokenizer(s);
			nivel=st.nextToken("#").trim();
	
			//pasa comentarios y lineas vacias de largo
			while(isVoid(s=inputString.readLine())){
			}
	
			//fil,col
			st = new StringTokenizer(s);
			cant=st.nextToken("#").trim();
			st = new StringTokenizer(cant,",");
			fil=Integer.parseInt(st.nextToken().trim());
			col=Integer.parseInt(st.nextToken().trim());
			
			//pasa comentarios y lineas vacias de largo
			while(isVoid(s=inputString.readLine())){
			}
		    
			//lee 
			String aux;
			ArrayList<Integer[]> celdas = new ArrayList<Integer[]>();
			int j=0;
			do{
				if(!isVoid(s)){
					st = new StringTokenizer(s,"#");
				    aux=st.nextToken();
				    String[] campos = aux.split(",");
					Integer celda[] = new Integer[7] ;
					if(campos.length==7){
						for( int i=0; i<7; i++){
							celda[i]=Integer.parseInt(campos[i].trim());
						}
						celdas.add(celda);
						j++;
					}
					else{
						JOptionPane.showMessageDialog(null,
								"Error en el archivo de " + nivel +" en la fila: "+j+". Se cerrara la aplicacion.",
								"Error",
								JOptionPane.ERROR_MESSAGE);
						System.exit(0);
						//throw new IOException("Error en el archivo de " + nivel +" en la fila: "+j);
					}
				} 
				  
			}while ((s = inputString.readLine()) != null);
	
			//creacion del tablero
			Tablero tablero = null;
			try{
				tablero = new Tablero(fil,col,nivel);
				if(guardado)
					tablero.setUser(user);
				for(Integer[] fila: celdas){
					Celda cel = new Celda();
					Espejo esp;
					if (fila[FILA]>=fil | fila[COL]>=col){
						System.err.println("No existe la posicion x: "+fila[FILA]+" Y:"+fila[COL]+" en el tablero de "+fil+"x"+col);
						return null; //hubo un error al cargar los datos.
					}
					
					switch(fila[TIPO]){
						case ORIG:
								try{
									Origen orig = new Origen(fila[ROT], fila[ROJO], fila[VERDE], fila[AZUL]);
									cel.agregarElemento(orig);
								}
								catch (OrigenException e){
									System.err.println("Problema con el origen");
									return null; //hubo un error al cargar los datos.
								}
								break;
						case DEST:
								try{
									Destino dest = new Destino(fila[ROT], fila[ROJO], fila[VERDE], fila[AZUL]);
									cel.agregarElemento(dest);
								}
								catch (DestinoException e){
									System.err.println("Problema con el destino");
									return null; //hubo un error al cargar los datos.
								}
								break;
						case SIMPLE:
								try{
									esp = new EspejoSimple(fila[ROT], fila[ROJO], fila[VERDE], fila[AZUL]);
									cel.agregarElemento(esp);
								}catch(EspejoException e){
									System.err.println("Problema con la informacion del espejo.");
									return null; //hubo un error al cargar los datos.
								}
								break;
						case DOBLE: 
								try{
									esp = new EspejoDoble(fila[ROT], fila[ROJO], fila[VERDE], fila[AZUL]);
									cel.agregarElemento(esp);
								}catch(EspejoException e){
									System.err.println("Problema con la informacion del espejo.");
									return null; //hubo un error al cargar los datos.
								}
								break;
						case SEMI:
								try{
									esp = new EspejoSemi(fila[ROT], fila[ROJO], fila[VERDE], fila[AZUL]);
									cel.agregarElemento(esp);
								}catch(EspejoException e){
									System.err.println("Problema con la informacion del espejo.");
									return null; //hubo un error al cargar los datos.
								}
								break;
						case PARED:
								try{
									Pared pared = new Pared(fila[ROT], fila[ROJO], fila[VERDE], fila[AZUL]);
									cel.agregarElemento(pared);
								}catch (ParedException e){
									System.err.println("Problema con la informacion de la pared.");
									return null; //hubo un error al cargar los datos.
								}
								break;
						case TRAMPA:
								try{
									Trampa trampa = new Trampa(fila[ROT], fila[ROJO], fila[VERDE], fila[AZUL]);
									cel.agregarElemento(trampa);
								}catch (TrampaException e){
									System.err.println("Problema con la informacion de la trampa.");
									return null; //hubo un error al cargar los datos.
								}
								break;
						default:
								System.err.println("Archivo hackeado. El tipo es invalido");
								return null; //hubo un error al cargar los datos.
					}
					tablero.agregarCelda(cel, fila[FILA], fila[COL]);
				}
			}catch (TableroException e){
				System.err.println("Error en los datos del tablero.");
			}
			return tablero;
		}catch (NumberFormatException e){
			return null; //ARCHIVO DE NIVEL MAL FORMADO.
		}
		
	}

	private boolean isVoid(String s){
		if(s!=null){
			s.trim();
			if(s.indexOf("#")==0 || s.length()==0)
				return true;
		    StringTokenizer st = new StringTokenizer(s,"#",true);
		    if(st.nextToken().trim().length()==0)
		    	return true;
		}
	    return false;
	}
}
